﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using Microsoft.Practices.Unity;
using Wyn.PMS.Common.Utils;
using Wyn.PMS.Entity.Entities;
using Wyn.PMS.Entity.IDataAccess;

namespace Wyn.PMS.Common.NightAudit
{
    /// <summary>
    /// 夜审预先检查
    /// <para>--------------------------</para>
    /// <para>@Author: cnalexi@gmail.com</para> 
    /// <para>@Create: 2012/5/15</para>  
    /// </summary>
    public class Precheck
    {
        public static bool IsCanAudit(HotelBizDay bizDay,HotelBizDay rootBizDay)
        {
            if(bizDay.BizDay!=rootBizDay.BizDay)
            {
                return false;
            }

            return true;
        }

        public static IList<HotelBizDay> GetCanAuditHotels(IEnumerable<HotelBizDay> allBizdays, HotelBizDay rootBizday, IHotelBizDayRepository bizDayRepository)
        {
            IList<HotelBizDay> canAuditHotels = new List<HotelBizDay>();

            foreach (var bizDay in allBizdays)
            {
                if (IsCanAudit(bizDay,rootBizday))
                {
                    canAuditHotels.Add(bizDay);
                
                }else
                {
                    //撤销自动夜审标记
                    //计入自动夜审预报警LOG

                }
            }

            return canAuditHotels;
        }


        /// <summary>
        /// 检查能夜审的订单 为空则顺利，不为空则不能顺利
        /// </summary>
        /// <param name="hotelId"></param>
        /// <returns></returns>
        public static IEnumerable<Order> CheckAuditOrders(IEnumerable<Order> orders,HotelBizDay bizDay)
        {
            //var inOrders = orders.Where(o => o.Status == EnumHelper.GetCode(OrderStatus.I)).ToList();

            string checkInTypeHR = EnumHelper.GetCode(CheckInType.HR);

            string checkInTypeDR = EnumHelper.GetCode(CheckInType.DR);

            IList<Order> excOrders = new List<Order>();

            foreach(var order in orders)
            {
                //租时过今天未续住
                //时租 和 白日不能过夜审
                if(order.DepartureDate.Date<=bizDay.BizDay 
                    ||order.CheckInType==checkInTypeHR 
                    ||order.CheckInType==checkInTypeDR)
                {
                    excOrders.Add(order);
                }
            }

            return excOrders;
        }

        public static IEnumerable<Reservation> CheckAuditReservations(IEnumerable<Reservation> reservations,HotelBizDay bizDay)
        {
            if (reservations == null || !reservations.Any()) return null;

            var statusR = EnumHelper.GetCode(ReserveStatus.R);

            DateTime bizTodayMax = bizDay.BizDay.AddDays(1).AddSeconds(-1);

            IList<Reservation> resvList= reservations.Where(r => r.StartDate <= bizTodayMax && r.Status == statusR).ToList();

            if (resvList.Count <= 0) return null;

            IUnityContainer container = UnityContainerService.GetContainer();

            IAccountRepository accountRepository = container.Resolve<IAccountRepository>();

            IList<Reservation> excResvs = new List<Reservation>();

            IList<Account> resvAccounts=null;

            var resvIdList = resvList.Select(r => r.ResvID).ToList();

            string hotelId = bizDay.HotelID;
            
            string accoutRootType_RV = EnumHelper.GetCode(AccountRootType.RV);

            string accoutStatusI = EnumHelper.GetCode(AccountStatus.I);
            
            Expression<Func<Account, bool>> exp = a => a.HotelID == hotelId
                                                       && a.Status == accoutStatusI
                                                       && a.AccountRootType == accoutRootType_RV
                                                       && resvIdList.Contains(a.ResvID);
                
            var transactionOptions = new System.Transactions.TransactionOptions();

            transactionOptions.IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted;

            using (var scope = new System.Transactions.TransactionScope(System.Transactions.TransactionScopeOption.Required, transactionOptions))
            {
                resvAccounts = accountRepository.BatchFind(hotelId, exp);

                scope.Complete();
            }

            IPreAuthorizationRepository preAuthRepository = container.Resolve<IPreAuthorizationRepository>();

            string pas_S = EnumHelper.GetCode(PreauthorizationStatus.S);

            IList<PreAuthorization> pres=null;

            using (var scope = new System.Transactions.TransactionScope(System.Transactions.TransactionScopeOption.Required, transactionOptions))
            {
                pres = preAuthRepository.BatchFind(hotelId,a =>a.HotelID == hotelId &&resvIdList.Contains(a.RelateID) &&a.Status == pas_S);
                
                scope.Complete();
            }

            if (resvAccounts != null && resvAccounts.Any())
            {
                var accountResvIds = resvAccounts.Select(a => a.ResvID).Distinct().ToList();
                excResvs = resvList.Where(r => accountResvIds.Contains(r.ResvID)).ToList();
            }

            if (pres != null && pres.Any())
            {
                var presResvIds = pres.Select(a=>a.RelateID).Distinct().ToList();
                var tempResvs = resvList.Where(r => presResvIds.Contains(r.ResvID)).ToList();
                excResvs = excResvs.Union(tempResvs).ToList();
            }

            return excResvs;
        }

        public static IEnumerable<AccountRoot> CheckAccountRoots(IEnumerable<AccountRoot> accountRoots,HotelBizDay bizDay)
        {

            return null;
        }
    }
}
